package com.ruoyi.business.service.impl;

import com.ruoyi.business.domain.BusinessFunctionTree;
import com.ruoyi.business.domain.ExtBusinessFunction;
import com.ruoyi.business.mapper.ExtBusinessFunctionMapper;
import com.ruoyi.business.service.IExtBusinessFunctionService;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 业务功能Service业务层处理
 *
 * @author ruoyi
 * @date 2024-01-08
 */
@Service
public class ExtBusinessFunctionServiceImpl implements IExtBusinessFunctionService
{
    @Autowired
    private ExtBusinessFunctionMapper extBusinessFunctionMapper;

    /**
     * 查询业务功能
     *
     * @param id 业务功能主键
     * @return 业务功能
     */
    @Override
    public ExtBusinessFunction selectExtBusinessFunctionById(Long id)
    {
        return extBusinessFunctionMapper.selectExtBusinessFunctionById(id);
    }

    /**
     * 查询业务功能列表
     *
     * @param extBusinessFunction 业务功能
     * @return 业务功能
     */
    @Override
    public List<ExtBusinessFunction> selectExtBusinessFunctionList(ExtBusinessFunction extBusinessFunction)
    {
        return extBusinessFunctionMapper.selectExtBusinessFunctionList(extBusinessFunction);
    }

    /**
     * 新增业务功能
     *
     * @param extBusinessFunction 业务功能
     * @return 结果
     */
    @Override
    public int insertExtBusinessFunction(ExtBusinessFunction extBusinessFunction)
    {
        //插入前检查
        //对象不能为空
        if(extBusinessFunction==null)
            throw new ServiceException("业务对象不为空!");
        //业务编码不为空
        if(StringUtils.isEmpty(extBusinessFunction.getBusinessCode()))
            throw new ServiceException("业务编码不为空!");
        //业务名称不能为空
        if(StringUtils.isEmpty(extBusinessFunction.getBusinessName()))
            throw new ServiceException("业务名称不为空!");
        //业务编码不重复
        Map<String,Object> searchMap = new HashMap<>();
        searchMap.put("businessCode",extBusinessFunction.getBusinessCode());
        if(extBusinessFunctionMapper.selectCount(searchMap)>0)
            throw new ServiceException("业务编码:"+extBusinessFunction.getBusinessCode()+"已存在!");
        //业务名称不能重复
        searchMap.clear();
        searchMap.put("businessName",extBusinessFunction.getBusinessName());
        if(extBusinessFunctionMapper.selectCount(searchMap)>0)
            throw new ServiceException("业务名称:"+extBusinessFunction.getBusinessName()+"已存在!");
        //父级编码非空时，必须存在
        if(!StringUtils.isEmpty(extBusinessFunction.getParentCode())){
            searchMap.clear();
            searchMap.put("businessCode",extBusinessFunction.getParentCode());
            if(extBusinessFunctionMapper.selectCount(searchMap)==0)
                throw new ServiceException("父级编码:"+extBusinessFunction.getParentCode()+"不存在!");
            //TODO:判断父节点是否挂业务模型、接口、页面。如果已经挂，禁止加子节点
        }
        extBusinessFunction.setCreateTime(DateUtils.getNowDate());
        return extBusinessFunctionMapper.insertExtBusinessFunction(extBusinessFunction);
    }

    /**
     * 修改业务功能
     *
     * @param extBusinessFunction 业务功能
     * @return 结果
     */
    @Override
    public int updateExtBusinessFunction(ExtBusinessFunction extBusinessFunction)
    {
        //更新前检查
        //对象不能为空
        if(extBusinessFunction==null)
            throw new ServiceException("业务对象不为空!");
        //id不能为空
        if(extBusinessFunction.getId()==null||extBusinessFunction.getId()==0L)
            throw new ServiceException("id为空!");
        //业务编码不为空
        if(StringUtils.isEmpty(extBusinessFunction.getBusinessCode()))
            throw new ServiceException("业务编码不为空!");
        //业务名称不能为空
        if(StringUtils.isEmpty(extBusinessFunction.getBusinessName()))
            throw new ServiceException("业务名称不为空!");
        //业务编码不重复
        Map<String,Object> searchMap = new HashMap<>();
        searchMap.put("businessCode",extBusinessFunction.getBusinessCode());
        searchMap.put("notId",extBusinessFunction.getId());
        if(extBusinessFunctionMapper.selectCount(searchMap)>0)
            throw new ServiceException("业务编码:"+extBusinessFunction.getBusinessCode()+"已存在!");
        //业务名称不能重复
        searchMap.clear();
        searchMap.put("notId",extBusinessFunction.getId());
        searchMap.put("businessName",extBusinessFunction.getBusinessName());
        if(extBusinessFunctionMapper.selectCount(searchMap)>0)
            throw new ServiceException("业务名称:"+extBusinessFunction.getBusinessName()+"已存在!");
        //父级编码非空时，必须存在
        if(!StringUtils.isEmpty(extBusinessFunction.getParentCode())){
            searchMap.clear();
            searchMap.put("businessCode",extBusinessFunction.getParentCode());
            if(extBusinessFunctionMapper.selectCount(searchMap)==0)
                throw new ServiceException("父级编码:"+extBusinessFunction.getParentCode()+"不存在!");
        }
        extBusinessFunction.setUpdateTime(DateUtils.getNowDate());
        return extBusinessFunctionMapper.updateExtBusinessFunction(extBusinessFunction);
    }

    /**
     * 批量删除业务功能
     *
     * @param ids 需要删除的业务功能主键
     * @return 结果
     */
    @Override
    public int deleteExtBusinessFunctionByIds(Long[] ids)
    {
        for(Long id:ids) {
            //检查是否有下级
            if (haveChild(id))
                throw new ServiceException("请先删除下级！");
        }
        return extBusinessFunctionMapper.deleteExtBusinessFunctionByIds(ids);
    }

    /**
     * 删除业务功能信息
     *
     * @param id 业务功能主键
     * @return 结果
     */
    @Override
    public int deleteExtBusinessFunctionById(Long id)
    {
        //检查是否有下级
        if(haveChild(id))
            throw new ServiceException("请先删除下级！");
        return extBusinessFunctionMapper.deleteExtBusinessFunctionById(id);
    }

    /**
     * 查询是否有下级
     * @param id 上级id
     * @return
     */
    private boolean haveChild(Long id) {
        Map<String,Object> searchMap = new HashMap<>();
        searchMap.put("parentId",id);
        return (extBusinessFunctionMapper.selectCount(searchMap)>0);
    }

    /**
     * 查询业务功能树
     *
     * @param extBusinessFunction
     * @return
     */
    @Override
    public List<ExtBusinessFunction> selectExtBusinessFunctionTree(ExtBusinessFunction extBusinessFunction) {
        List<ExtBusinessFunction> list = extBusinessFunctionMapper.selectExtBusinessFunctionList(extBusinessFunction);
        List<ExtBusinessFunction> treeList = buildTree(list);
        return treeList;
    }

    /**
     * 根据条件查询满足条数
     *
     * @param searchMap 查询条件
     * @return 条数
     */
    @Override
    public int searchCount(Map<String, Object> searchMap) {
        return extBusinessFunctionMapper.selectCount(searchMap);
    }

    /**
     * 判断业务编码是否为末级
     *
     * @param extBusinessFunction
     * @return
     */
    @Override
    public boolean isLastLevel(ExtBusinessFunction extBusinessFunction) {
        //校验
        if(StringUtils.isEmpty(extBusinessFunction.getBusinessCode()))
            throw  new ServiceException("业务编码为空!");
        Map<String, Object> searchMap = new HashMap<>();
        searchMap.put("parentCode",extBusinessFunction.getBusinessCode());
        if(searchCount(searchMap)>0){
            return false;
        }else {
            return true;
        }
    }

    /**
     * 构造功能树
     * @param list
     * @return
     */
    private List<ExtBusinessFunction> buildTree(List<ExtBusinessFunction> list) {
        List<ExtBusinessFunction> retList = new ArrayList<>();

        //循环构造第一级
        for(ExtBusinessFunction function:list){
            if(StringUtils.isEmpty(function.getParentCode())){
                retList.add(recursionMakeTreeNode(function,list));
            }
        }
        return retList;
    }

    /**
     * 递归构造当前节点及下级节点
     * @param function
     * @param list
     * @return
     */
    private ExtBusinessFunction recursionMakeTreeNode(ExtBusinessFunction function, List<ExtBusinessFunction> list) {
         //获取直接下级
        List<ExtBusinessFunction> childList = list.stream().filter(item->function.getBusinessCode().equals(item.getParentCode())).collect(Collectors.toList());
        function.setChildren(childList);
        //递归下级
        for(ExtBusinessFunction child:childList){
            recursionMakeTreeNode(child,list);
        }
        return function;
    }
    /**
     * 查询业务功能树,通用查询
     *
     * @param extBusinessFunction
     * @return
     */
    @Override
    public List<BusinessFunctionTree> selectCommonBusinessFunctionTree(ExtBusinessFunction extBusinessFunction) {
        List<BusinessFunctionTree> list = extBusinessFunctionMapper.selectCommonBusinessFunctionList(extBusinessFunction);
        List<BusinessFunctionTree> treeList = buildCommonTree(list);
        return treeList;
    }

    /**
     * 构造通用树
     * @param list
     * @return
     */
    private List<BusinessFunctionTree> buildCommonTree(List<BusinessFunctionTree> list) {
        List<BusinessFunctionTree> retList = new ArrayList<>();

        //循环构造第一级
        for(BusinessFunctionTree function:list){
            if(StringUtils.isEmpty(function.getParentCode())){
                retList.add(recursionMakeCommonTreeNode(function,list));
            }
            function.setNodeType(BusinessFunctionTree.NODE_TYPE_BUSINESS);
            function.setHasChildren(true);
        }
        return retList;
    }
    /**
     * 递归构造当前节点及下级节点
     * @param function
     * @param list
     * @return
     */
    private BusinessFunctionTree recursionMakeCommonTreeNode(BusinessFunctionTree function, List<BusinessFunctionTree> list) {
        //获取直接下级
        List<BusinessFunctionTree> childList = list.stream().filter(item->function.getValue().equals(item.getParentCode())).collect(Collectors.toList());
        for(BusinessFunctionTree child:childList){
            child.setNodeType(BusinessFunctionTree.NODE_TYPE_BUSINESS);
            child.setHasChildren(true);
        }
        function.setChildren(childList);
        //递归下级
        for(BusinessFunctionTree child:childList){
            recursionMakeCommonTreeNode(child,list);
        }
        return function;
    }
}
